package com.spring.AOP;


import com.spring.AOP.AopAnnotation.*;
import com.spring.AOP.AopInterface.ProxyFactory;
import com.spring.springInterface.BeanDefinition;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

public class DefaultProxyFactory implements ProxyFactory {
    private final ProxyRegister proxyRegister;
    PointCutMatcher pointCutMatcher = new PointCutMatcher();
    public DefaultProxyFactory(Map<String, BeanDefinition> beanDefinitionMap) {
        this.proxyRegister=new ProxyRegister(beanDefinitionMap);
    }
    Map<String, List<MethodInfo>> beanMethodInfoMap = new HashMap<>();

    public void register() {
        proxyRegister.register();
    }

    public Object createProxyIfNeedAop(Object bean, String beanName) throws ClassNotFoundException {
        //register();
        boolean proxyNeeded = needAopProxy(beanName, bean);
        if (!proxyNeeded) {
            return bean; // 不需要代理，返回原生Bean
        }
        if ( bean.getClass().getInterfaces().length > 0) {
          return createJdkProxy(bean,beanName);
        }else{
            return createCglibProxy(bean,beanName);
        }
    }

        private boolean hasInterfaces(Class<?> clazz) {
            Class<?>[] interfaces = clazz.getInterfaces();
            return interfaces.length > 0 && !interfaces[0].equals(Object.class);
        }



    private Object createJdkProxy(Object bean,String beanName)  {
        Class<?> beanClass = bean.getClass();
        return Proxy.newProxyInstance(
                beanClass.getClassLoader(),
                beanClass.getInterfaces(), // 注意：JDK代理需要接口
                new AopHandler(bean, proxyRegister.getAspectAdviceMap(), beanMethodInfoMap,pointCutMatcher)
        );
    }

    private Object createCglibProxy(Object bean, String beanName) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(bean.getClass()); // 设置父类（目标类）
        enhancer.setCallback((MethodInterceptor) (proxy, method, args, methodProxy) -> {
            // 复用AopHandler的逻辑处理通知（通过适配器模式适配CGLIB回调）
            AopHandler handler = new AopHandler(bean, proxyRegister.getAspectAdviceMap(), beanMethodInfoMap, pointCutMatcher);
            return handler.invoke(proxy, method, args);
        });
        return enhancer.create(); // 创建代理实例
    }
    private Set<String> resolvePointcutExpressions() {
        Set<String> expressions = new HashSet<>();

        for (Map.Entry<Object, Map<Class<?>, List<Method>>> aspectEntry : proxyRegister.getAspectAdviceMap().entrySet()) {
            Map<Class<?>, List<Method>> adviceMap = aspectEntry.getValue();

            for (List<Method> adviceMethods : adviceMap.values()) {
                for (Method adviceMethod : adviceMethods) {
                    // 提取所有注解中的切入点表达式
                    if (adviceMethod.isAnnotationPresent(Before.class)) {
                        expressions.add(adviceMethod.getAnnotation(Before.class).value());
                    } else if (adviceMethod.isAnnotationPresent(After.class)) {
                        expressions.add(adviceMethod.getAnnotation(After.class).value());
                    } else if (adviceMethod.isAnnotationPresent(Around.class)) {
                        expressions.add(adviceMethod.getAnnotation(Around.class).value());
                    }
                }
            }
        }

        return expressions;
    }

    public boolean needAopProxy(String beanName, Object bean) {
       //register();
//       拿到所有的目标方法
        List<Method> methods = Arrays.asList(bean.getClass().getMethods());
//        拿到所有的切点表达式
        Set<String> pointcutExpressions = resolvePointcutExpressions();
        List<MethodInfo> matchedMethods = pointCutMatcher.matchAndCollectMethods(methods, pointcutExpressions);
        if (!matchedMethods.isEmpty()) {
            beanMethodInfoMap.put(beanName, matchedMethods);
            return true;
        }
        return false;
    }
}
